package com.example.watchimageh264

import android.content.Intent
import android.graphics.*
import android.media.*
import android.media.projection.MediaProjectionManager
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import java.io.DataOutputStream
import java.io.IOException
import java.net.Socket
import java.util.concurrent.Executors
import android.view.Menu
import android.view.MenuItem
import android.view.Surface
import androidx.navigation.findNavController

class MainActivity : AppCompatActivity() {
    private var sps: ByteArray? = null
    private var pps: ByteArray? = null
    private val REQUEST_CODE = 1000
    private lateinit var projectionManager: MediaProjectionManager
    private var mediaProjection: android.media.projection.MediaProjection? = null

    private lateinit var imageReader: ImageReader
    private var socket: Socket? = null
    private var outputStream: DataOutputStream? = null

    private var encoder: MediaCodec? = null
    private var inputSurface: Surface? = null

    // 线程池
    private val connectExecutor = Executors.newSingleThreadExecutor()
    private val sendExecutor = Executors.newSingleThreadExecutor()

    // 录制参数
    private val width = 1280
    private val height = 720
    private val bitrate = 2000000
    private val frameRate = 30

    // 标记SPS和PPS是否已发送
    private var spsPpsSent = false

    // 添加一个标志，跟踪连接状态
    private var isConnected = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val intent = Intent(this, MyMediaProjectionService::class.java)
        ContextCompat.startForegroundService(this, intent)

        // 初始化MediaProjection
        projectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
        startActivityForResult(projectionManager.createScreenCaptureIntent(), REQUEST_CODE)

        // 连接服务器
        connectToServer()
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == REQUEST_CODE && resultCode == RESULT_OK && data != null) {
            Log.d("MainActivity", "获得屏幕捕获权限")
            mediaProjection = projectionManager.getMediaProjection(resultCode, data)
            initEncoder()
            startCapture()
        } else {
            Log.e("MainActivity", "没有获得屏幕捕获权限或失败")
        }
        super.onActivityResult(requestCode, resultCode, data)
    }

    private fun initEncoder() {
        val format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height)
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
        format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate)
        format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate)
        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1)

        // 添加以下配置以稳定编码器输出
        format.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR)
        // 修复类型不匹配问题，将 Int 转换为 Long
        format.setLong(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, (1000000 / frameRate).toLong())

        // 设置编码器配置文件和级别
        format.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh)
        format.setInteger(MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel41)

        try {
            encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC)
            encoder?.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
            inputSurface = encoder?.createInputSurface()
            encoder?.start()
            Log.d("Encoder", "编码器初始化成功")
        } catch (e: IOException) {
            Log.e("Encoder", "初始化编码器失败：${e.message}")
            e.printStackTrace()
        }
    }


    private fun startCapture() {
        // 创建两个独立的线程分别处理绘制和编码
        // 1. 绘制线程
        Thread {
            try {
                while (true) {
                    val canvas = inputSurface?.lockCanvas(null)
                    if (canvas != null) {
                        val paint = Paint()
                        paint.color = getRandomColor()
                        canvas.drawColor(paint.color)

                        // 添加一些文本和图形，提供更多视觉反馈
                        paint.color = Color.WHITE
                        paint.textSize = 48f
                        val timestamp = System.currentTimeMillis()
                        canvas.drawText("Stream: $timestamp", 50f, height / 2f, paint)

                        // 画一个移动的圆形，用于验证视频流动性
                        val radius = 50f
                        val cx = (width / 2 + Math.sin(timestamp / 500.0) * (width / 4)).toFloat()
                        val cy = (height / 2 + Math.cos(timestamp / 500.0) * (height / 4)).toFloat()
                        paint.color = Color.YELLOW
                        canvas.drawCircle(cx, cy, radius, paint)

                        inputSurface?.unlockCanvasAndPost(canvas)
                        Log.d("Capture", "绘制一帧: ${timestamp}")
                    } else {
                        Log.e("Capture", "无法锁定Surface")
                    }
                    Thread.sleep((1000 / frameRate).toLong())
                }
            } catch (e: Exception) {
                Log.e("Capture", "绘制线程异常：${e.message}")
                e.printStackTrace()
            }
        }.start()

        // 2. 编码线程
        Thread {
            try {
                val bufferInfo = MediaCodec.BufferInfo()
                var lastKeyFrameTime = 0L

                while (true) {
                    // 检查编码器状态
                    if (encoder == null) {
                        Log.e("Encoder", "编码器为空")
                        break
                    }

                    // 每隔2秒请求一个关键帧
                    val currentTime = System.currentTimeMillis()
                    if (currentTime - lastKeyFrameTime > 2000) {
                        val params = Bundle()
                        params.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0)
                        encoder?.setParameters(params)
                        lastKeyFrameTime = currentTime
                        Log.d("Encoder", "请求关键帧")
                    }

                    val outputBufferId = encoder?.dequeueOutputBuffer(bufferInfo, 10000)

                    when (outputBufferId) {
                        MediaCodec.INFO_OUTPUT_FORMAT_CHANGED -> {
                            Log.d("Encoder", "输出格式已更改")
                            val format = encoder?.outputFormat
                            // 获取SPS和PPS
                            format?.getByteBuffer("csd-0")?.let { spsBuffer ->
                                sps = ByteArray(spsBuffer.remaining())
                                spsBuffer.get(sps!!)
                                Log.d("Encoder", "获取到SPS，大小：${sps?.size}")

                                // 打印SPS内容用于调试
                                val spsHex = sps?.joinToString("") {
                                    String.format("%02X", it)
                                }
                                Log.d("Encoder", "SPS内容: $spsHex")
                            }
                            format?.getByteBuffer("csd-1")?.let { ppsBuffer ->
                                pps = ByteArray(ppsBuffer.remaining())
                                ppsBuffer.get(pps!!)
                                Log.d("Encoder", "获取到PPS，大小：${pps?.size}")

                                // 打印PPS内容用于调试
                                val ppsHex = pps?.joinToString("") {
                                    String.format("%02X", it)
                                }
                                Log.d("Encoder", "PPS内容: $ppsHex")
                            }

                            // 一旦获得SPS和PPS，立即发送它们
                            if (!spsPpsSent && sps != null && pps != null) {
                                sendH264Frame(sps!!, true, false)
                                sendH264Frame(pps!!, false, false)
                                spsPpsSent = true
                                Log.d("Encoder", "已发送SPS和PPS")
                            }
                        }
                        MediaCodec.INFO_TRY_AGAIN_LATER -> {
                            Log.d("Encoder", "暂无可用的输出缓冲区")
                            Thread.sleep(10)
                            continue
                        }
                        MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED -> {
                            Log.d("Encoder", "输出缓冲区已更改")
                        }
                        else -> {
                            if (outputBufferId != null && outputBufferId >= 0) {
                                val encodedBuffer = encoder?.getOutputBuffer(outputBufferId)
                                if (encodedBuffer != null && bufferInfo.size > 0) {
                                    val frameBytes = ByteArray(bufferInfo.size)
                                    encodedBuffer.position(bufferInfo.offset)
                                    encodedBuffer.limit(bufferInfo.offset + bufferInfo.size)
                                    encodedBuffer.get(frameBytes)

                                    val isKeyFrame = (bufferInfo.flags and MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0
                                    val isConfigFrame = (bufferInfo.flags and MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0

                                    Log.d("Encoder", "编码成功，帧大小：${bufferInfo.size}，" +
                                            "是否关键帧：$isKeyFrame，" +
                                            "是否配置帧：$isConfigFrame，" +
                                            "时间戳：${bufferInfo.presentationTimeUs}")

                                    // 如果是关键帧（I帧），先发送SPS和PPS
                                    if (isKeyFrame && sps != null && pps != null) {
                                        sendH264Frame(sps!!, true, false)
                                        sendH264Frame(pps!!, false, false)
                                        Log.d("Encoder", "关键帧前发送SPS和PPS")
                                    }

                                    // 对于普通帧，直接发送
                                    if (!isConfigFrame) {
                                        sendH264Frame(frameBytes, isKeyFrame, true)
                                    }
                                }
                                encoder?.releaseOutputBuffer(outputBufferId, false)
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                Log.e("Encoder", "编码线程异常：${e.message}")
                e.printStackTrace()
            }
        }.start()
    }

    private fun getRandomColor(): Int {
        val rnd = java.util.Random()
        return Color.rgb(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256))
    }

    // 修改后的发送方法，添加了类型标记和完整性检查
    private fun sendH264Frame(frameData: ByteArray, isKeyFrame: Boolean, isNormalFrame: Boolean) {
        if (!isConnected || outputStream == null) {
            Log.e("SendH264", "未连接到服务器，无法发送帧")
            return
        }

        Log.d("SendH264", "准备发送一帧，大小：${frameData.size}，是否关键帧：$isKeyFrame，是否普通帧：$isNormalFrame")

        sendExecutor.execute {
            try {
                // 识别NALU类型，用于调试
                /*
                if (frameData.isNotEmpty()) {
                    val naluType = frameData[0] & 0x1F
                    val naluTypeName = when (naluType) {
                        1 -> "P帧"
                        5 -> "I帧"
                        6 -> "SEI"
                        7 -> "SPS"
                        8 -> "PPS"
                        else -> "其他($naluType)"
                    }
                    Log.d("NALU", "帧类型: $naluTypeName")
                }

                 */
                if (frameData.isNotEmpty()) {
                    // 修复位运算问题
                    val naluType = frameData[0].toInt() and 0x1F
                    val naluTypeName = when (naluType) {
                        1 -> "P帧"
                        5 -> "I帧"
                        6 -> "SEI"
                        7 -> "SPS"
                        8 -> "PPS"
                        else -> "其他($naluType)"
                    }
                    Log.d("NALU", "帧类型: $naluTypeName, 数据长度: ${frameData.size}")

                    // 修复字符串连接问题
                    val prefix = frameData.take(10).joinToString(",") { it.toString() }
                    Log.d("NALU", "数据前缀: $prefix")
                }
                // 创建包含NALU前导码的完整帧
                // 使用标准的H.264 NALU起始码: 0x00 0x00 0x00 0x01
                val buf = ByteArray(frameData.size + 4)
                buf[0] = 0x00.toByte()
                buf[1] = 0x00.toByte()
                buf[2] = 0x00.toByte()
                buf[3] = 0x01.toByte()
                System.arraycopy(frameData, 0, buf, 4, frameData.size)

                // 计算并写入数据大小
                val frameSize = buf.size

                // 写入帧大小（4字节整数，大端序）
                outputStream?.writeInt(frameSize)

                // 写入帧数据
                outputStream?.write(buf)
                outputStream?.flush()

                Log.d("Transmit", "已发出一帧，大小：${frameSize}字节，" +
                        "是否关键帧：$isKeyFrame，是否普通帧：$isNormalFrame")

                // 打印帧前16字节用于调试
                val hexData = buf.take(Math.min(16, buf.size)).joinToString("") {
                    String.format("%02X", it)
                }
                Log.d("Transmit", "帧前16字节: $hexData")

            } catch (e: IOException) {
                Log.e("Transmit", "发送失败：${e.message}")
                isConnected = false
                reconnect()
            }
        }
    }

    private fun reconnect() {
        Log.d("Reconnect", "尝试重连")
        try {
            outputStream?.close()
            socket?.close()
        } catch (e: Exception) {
            Log.e("Reconnect", "关闭旧socket异常：${e.message}")
        }
        spsPpsSent = false  // 重置SPS/PPS发送标志
        connectToServer() // 重新连接
    }

    private fun connectToServer() {
        connectExecutor.execute {
            try {
                socket = Socket("192.168.10.219", 8080)
                outputStream = DataOutputStream(socket!!.getOutputStream())
                isConnected = true
                Log.d("Socket", "Socket连接成功")

                // 连接成功后，如果已经有SPS和PPS，则立即发送
                if (sps != null && pps != null) {
                    sendH264Frame(sps!!, true, false)
                    sendH264Frame(pps!!, false, false)
                    spsPpsSent = true
                    Log.d("Socket", "连接后发送SPS和PPS")
                }
            } catch (e: IOException) {
                isConnected = false
                Log.e("Socket", "连接失败：${e.message}")
                // 添加延迟重连逻辑，避免无限循环重连
                Thread.sleep(3000)
                connectToServer()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        try {
            outputStream?.close()
            socket?.close()
            encoder?.stop()
            encoder?.release()
            inputSurface?.release()
        } catch (e: Exception) {
            Log.e("Close", "关闭资源异常：${e.message}")
        }
        connectExecutor.shutdownNow()
        sendExecutor.shutdownNow()
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.action_settings -> true
            else -> super.onOptionsItemSelected(item)
        }
    }
}

